" < C/C++ Compile, Link, and Run, for Acm >
" Related Works:
"   Svtter/ACM.vim
"   c-support
"   vim-scripts/c.vim

" %<.o
" exe ':bo cope'
" exe ':bo cw'
" let v:statusmsg = ''
" empty(v:statusmsg)
" exe 'let &l:makeprg="' . s:windows_CPPFlags.Exe . '"'

let s:gen_ext = g:Windows ? '.exe':''

function! s:OnEvent(job_id, data, event) dict
  if a:event == 'exit'
    silent Neomake!
  endif

  " call append(line('$'), str)
endfunction
let s:callbacks = {
      \ 'on_exit': function('s:OnEvent')
      \ }

" TODO 路径依赖
" TODO 支持中文源文件名
let $OJ = expand('~/OJ')
let $OJ_BUILD = expand('~/OJ/build')
func! acm#compile()
  let Src = expand("%:p")
  let ext = expand("%:e")
  let Exe = expand("%:p:t:r").s:gen_ext
  if ext == "c" || ext == "cpp" || ext == "cxx" || ext == "cc"
    " let save = &makeprg
    exe ":ccl"
    exe ":update"
    " On Windows, rename `mingw32-make.exe` to `make.exe`
    if g:Windows
      let CRLF = "\r\n"
      " Q: 如果jobstart的命令还没有执行完成，chansend发送命令，此时的行为是怎么样的
      let job1 = jobstart('cmd.exe /k "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"', extend({'shell': 'shell1'}, {'on_exit':function('WinAcmJobFinished')}))
      if strlen(Exe) != strchars(Exe)
        " cant work, build时nmake报错
        let cmake = printf('cmake -G "NMake Makefiles"  -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++  -DCMAKE_EXPORT_COMPILE_COMMANDS=YES  -S %s -B %s -DMAIN:STRING="%s" -DTARGET:STRING=%s', $OJ, $OJ_BUILD, Src, 'test') . CRLF
      else
        let cmake = printf('cmake -G "NMake Makefiles"  -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++  -DCMAKE_EXPORT_COMPILE_COMMANDS=YES  -S %s -B %s -DMAIN:STRING="%s"', $OJ, $OJ_BUILD, Src) . CRLF
      endif
      call chansend(job1, cmake)
      call chansend(job1, "cmake --build ".$OJ_BUILD.CRLF)
      call chansend(job1, "exit".CRLF)
    else
      " let &l:makeprg = 'make -C ' . expand("%:p:h") . ' OBJS=' . Exe
      if strlen(Exe) != strchars(Exe)
        let str = printf('cmake -S %s -B %s -DMAIN:STRING="%s" -DTARGET:STRING=%s ..', $OJ, $OJ_BUILD, Src, 'test')
      else
        let str = printf('cmake -S %s -B %s -DMAIN:STRING="%s" ..', $OJ, $OJ_BUILD, Src)
      endif
      let &l:makeprg = 'make -C ' . $OJ_BUILD
      let job1 = jobstart(['bash', '-c', str], extend({'shell': 'shell1'}, s:callbacks))
    endif
    " let &l:makeprg = save
  elseif ext == "py"
    if has('nvim')
      exe 'split'
    endif
    let cmd = printf('terminal python3 "%s"', Src)
    exe cmd
  else
    echohl WarningMsg | echo " Incorrect source file"
  endif
endfunc

function! WinAcmJobFinished(job_id, data, event) abort
  let EXE = $OJ_BUILD . '/' . expand("%:p:t:r") . s:gen_ext
  let SRC = expand("%:p:h")
  if has('nvim')
    exe 'split'
  endif
  exe 'lcd' SRC
  if strlen(EXE) != strchars(EXE)
    let EXE = $OJ_BUILD . '/' . 'test'
  endif
  exe 'terminal' EXE
  setlocal nonumber norelativenumber
  echom EXE
endfunction

function! AcmJobFinished() abort
  let context = g:neomake_hook_context
  if context.jobinfo.exit_code == 0 && context.jobinfo.maker.args!=[] && context.jobinfo.maker.args[1] =~ 'build'
    " let EXE = expand("%:p:h").'/exes/'.expand("%:p:t:r").s:gen_ext
    let EXE = $OJ_BUILD . '/' . expand("%:p:t:r")
    let SRC = expand("%:p:h")
    if has('nvim')
      exe 'split'
    endif
    exe 'lcd' SRC
    if strlen(EXE) != strchars(EXE)
      let EXE = $OJ_BUILD . '/' . 'test'
    endif
    exe 'terminal' EXE
    setlocal nonumber norelativenumber
    " setlocal statusline=%{b:term_title}
    echom EXE
  else
    echom printf('The job for maker %s exited non-zero: %s', context.jobinfo.maker.name, context.jobinfo.exit_code)
    call luaeval('print(vim.inspect(_A))', context.jobinfo)
  endif
endfunction
autocmd MyAutoCmd User NeomakeJobFinished call AcmJobFinished()
